﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using TekaMUD.Engine.Framework;
using TekaMUD.Engine.ServerTasks;

namespace TekaMUD.Engine.Workers
{
	public class WorkerThreadScheduler : WorkerThread, ISingleWorker
	{
		public WorkerThreadScheduler(): base("Scheduler Thread")
		{
		}

		protected override void Run()
		{
			while (!Terminated)
			{
				if(Terminated)
					goto cleanup;

				// Blocking call
				Node<Task> minNode = SchedulerQueue.DequeueTask();

				Logger.LogDebug("Dequeued task " + minNode.data.Name);

				long CurrentTimeTicks = DateTime.Now.Ticks;

				if (CurrentTimeTicks < minNode.key)
					Thread.Sleep(new TimeSpan(minNode.key - CurrentTimeTicks));
				
				
				Locks.StorageLock.EnterReadLock();


				// Execute the task.
				Logger.LogDebug("Executing task: " + minNode.data.Name);
				minNode.data.Execute();
				Locks.StorageLock.ExitReadLock();

				// Check if the task should be run again.
				if (minNode.data is IRepeatableTask)
				{
					IRepeatableTask irt = minNode.data as IRepeatableTask;

					// Calculate the next invocation time.
					switch(irt.RepeatType)
					{
						case RepeatableTaskType.Date:
							long ticks = irt.GetNextRunDate().Ticks;

							if(ticks  > DateTime.Now.Ticks)
								SchedulerQueue.Insert(minNode.data, ticks);

							break;
	
						case RepeatableTaskType.Interval:
							SchedulerQueue.Insert(minNode.data, minNode.key + irt.GetNextRunInterval().Ticks);
							break;

					}
				}

				LastRun = DateTime.Now;
			}

		cleanup:
			Logger.LogInfo("[Thread] Scheduler worker terminated.");
		}
	}
}
